/**
 * 广寒宫
 * 网址:www.guanghangong.xyz
 */
package org.moon.framework.autoconfigure.oss.impl;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.moon.framework.autoconfigure.exception.domain.MoonException;
import org.moon.framework.autoconfigure.oss.OssService;
import org.moon.framework.autoconfigure.oss.domain.MoonFile;
import org.moon.framework.autoconfigure.oss.props.OssProperties;
import org.moon.framework.autoconfigure.oss.utils.OssUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PreDestroy;
import java.io.*;
import java.time.LocalDate;
import java.util.List;

/**
 * scp 上传文件到远程nginx
 * @author moon
 */
@Slf4j
public class ScpOssProviderImpl implements OssService {

	private OssProperties ossProperties;
	private Connection conn;

	public ScpOssProviderImpl(OssProperties ossProperties){
		this.ossProperties = ossProperties;
		login();
	}
	

	@PreDestroy
	public void clean(){
		if(conn!=null && conn.isAuthenticationComplete()){
			conn.close();
		}
	}

	@Override
	public MoonFile putFile(MultipartFile file) {
		return putFile(OssUtils.getFileName(file.getOriginalFilename()),file);
	}

	@Override
	public MoonFile putFile(String fileName, MultipartFile file) {
		String bucketName = OssUtils.getBucketName(ossProperties.getBucketName());
		LocalDate date = LocalDate.now();
		String remoteFileDir = bucketName + "/" + date.getYear() + "/" + date.getMonthValue() + "/" + date.getDayOfMonth();
		try {
			checkLogin(conn);
			//生成目录
			execShellScript("mkdir -p " + remoteFileDir);
			SCPClient client = new SCPClient(conn);
			client.put(file.getBytes(),fileName,remoteFileDir, "0644");
			MoonFile moonFile = MoonFile.builder().originalName(fileName).name(fileName).domain(this.ossProperties.getEndpoint()).link(bucketName.concat("/").concat(fileName)).build();
			return moonFile;
		}catch (Exception e){
			log.error(e.getMessage(),e);
			return null;
		}
	}

	@Override
	public void removeFiles(List<String> fileNames) {
		log.error("scp方式不支持删除...");
	}

	@Override
	public void removeFile(String fileNames) {
		log.error("scp方式不支持删除...");
	}
	/**
	 * 登录服务器
	 */
	private void login(){
		long t = System.currentTimeMillis();
		log.info("开启初始化scp...");
		String [] up = ossProperties.getEndpoint().split(":");
		conn = new Connection(up[0],Integer.valueOf(up[1]));
		try {
			conn.connect();
			boolean isAuthenticated = conn.authenticateWithPassword(ossProperties.getAccessKey(), ossProperties.getSecretKey());
			if (isAuthenticated == false) {
				throw new MoonException("scp authentication failed");
			}
		}catch (Exception e){
			log.error(e.getMessage(),e);
			throw new MoonException("scp authentication failed");
		}
		log.info("scp 初始化完成,用时{}",System.currentTimeMillis()-t);
	}

	/**
	 * 执行脚本
	 */
	private void execShellScript(String cmd)throws IOException {
		Session sess = null;
		InputStream stdout = null;
		BufferedReader br = null;
		StringBuffer buffer = new StringBuffer("exec result:");
		buffer.append(System.getProperty("line.separator"));
		try {
			sess = conn.openSession();
			sess.execCommand(cmd);
			stdout = new StreamGobbler(sess.getStdout());
			br = new BufferedReader(new InputStreamReader(stdout));
			while (true) {
				String line = br.readLine();
				if (line == null){
					break;
				}
				buffer.append(line);
				buffer.append(System.getProperty("line.separator"));
			}
		}catch(Exception e){
			log.error(e.getMessage(),e);
		} finally {
			try {
				if(stdout!=null){
					stdout.close();
				}
				if(br!=null){
					br.close();
				}
			} catch (IOException e) {
				log.error(e.getMessage(), e);
			}
			if(sess!=null){
				sess.close();
			}
		}
	}
	private void checkLogin(Connection conn){
		if(conn==null || !conn.isAuthenticationComplete()){
			login();
			log.warn("scp 重新登录...");
		}
		try {
			Session sess = conn.openSession();
			sess.close();
		} catch (Exception e) {
			login();
			log.warn("scp 重新登录...");
		}
	}
}